using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using Pinwheel.LSerialize;

namespace Pinwheel.Kernel
{
    [LSerializable]
    [StructLayout(LayoutKind.Explicit, Size = 4)]
    public partial struct IPv4
    {
        [FieldOffset(0)]
        public byte ipv40;
        [FieldOffset(1)]
        public byte ipv41;
        [FieldOffset(2)]
        public byte ipv42;
        [FieldOffset(3)]
        public byte ipv43;
        
        // 正则表达式验证 IPv4 地址格式
        private static readonly Regex IPv4Regex = new Regex(@"^(\d{1,3}\.){3}\d{1,3}$");
        
        public IPv4(byte ipv40, byte ipv41, byte ipv42, byte ipv43)
        {
            this.ipv40 = ipv40;
            this.ipv41 = ipv41;
            this.ipv42 = ipv42;
            this.ipv43 = ipv43;
        }
        
        public IPv4(string address)
        {
            if (!IPv4Regex.IsMatch(address))
            {
                throw new ArgumentException("Invalid IPv4 address format.");
            }
            
            var parts = address.Split('.');
            try
            {
                ipv40 = ParseByte(parts[0]);
                ipv41 = ParseByte(parts[1]);
                ipv42 = ParseByte(parts[2]);
                ipv43 = ParseByte(parts[3]);
            }
            catch (Exception ex)
            {
                throw new ArgumentException("Invalid IPv4 address values.", ex);
            }
        }
        
        private static byte ParseByte(string part)
        {
            int value = int.Parse(part);
            if (value < 0 || value > 255)
            {
                throw new ArgumentOutOfRangeException(nameof(part), "IPv4 segments must be between 0 and 255.");
            }
            return (byte)value;
        }
    }
    
    [LSerializable]
    [StructLayout(LayoutKind.Explicit, Size = 16)]
    public partial struct IPv6
    {
        [FieldOffset(0)]
        public ushort ipv60;
        [FieldOffset(2)]
        public ushort ipv61;
        [FieldOffset(4)]
        public ushort ipv62;
        [FieldOffset(6)]
        public ushort ipv63;
        [FieldOffset(8)]
        public ushort ipv64;
        [FieldOffset(10)]
        public ushort ipv65;
        [FieldOffset(12)]
        public ushort ipv66;
        [FieldOffset(14)]
        public ushort ipv67;

        // 正则表达式验证展开后的 IPv6 地址格式（没有 ::）
        private static readonly Regex FullIPv6Regex = new Regex(@"^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$");

        public IPv6(ushort ipv60, ushort ipv61, ushort ipv62, ushort ipv63, ushort ipv64, ushort ipv65, ushort ipv66, ushort ipv67)
        {
            this.ipv60 = ipv60;
            this.ipv61 = ipv61;
            this.ipv62 = ipv62;
            this.ipv63 = ipv63;
            this.ipv64 = ipv64;
            this.ipv65 = ipv65;
            this.ipv66 = ipv66;
            this.ipv67 = ipv67;
        }

        public IPv6(string address)
        {
            // 展开地址中的压缩形式（如 ::）
            var expandedAddress = ExpandIPv6Address(address);
            
            // 验证展开后的地址格式
            if (!FullIPv6Regex.IsMatch(expandedAddress))
            {
                throw new ArgumentException("Invalid IPv6 address format.");
            }

            // 将展开后的地址分割为 8 个段
            var parts = expandedAddress.Split(':');
            if (parts.Length != 8)
            {
                throw new ArgumentException("IPv6 address must have exactly 8 segments.");
            }

            ipv60 = ParseUShort(parts[0]);
            ipv61 = ParseUShort(parts[1]);
            ipv62 = ParseUShort(parts[2]);
            ipv63 = ParseUShort(parts[3]);
            ipv64 = ParseUShort(parts[4]);
            ipv65 = ParseUShort(parts[5]);
            ipv66 = ParseUShort(parts[6]);
            ipv67 = ParseUShort(parts[7]);
        }

        private static ushort ParseUShort(string part)
        {
            if (!ushort.TryParse(part, System.Globalization.NumberStyles.HexNumber, null, out ushort value))
            {
                throw new ArgumentOutOfRangeException(nameof(part), "IPv6 segments must be valid hexadecimal numbers between 0 and FFFF.");
            }
            return value;
        }

        private static string ExpandIPv6Address(string address)
        {
            // 检查是否含有 ::
            if (address.Contains("::"))
            {
                var sides = address.Split(new[] { "::" }, StringSplitOptions.None);

                // 分离两部分，并根据需要补充 0 段
                var leftSide = sides[0].Split(new[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                var rightSide = sides.Length > 1 ? sides[1].Split(new[] { ':' }, StringSplitOptions.RemoveEmptyEntries) : Array.Empty<string>();

                // 计算需要补全的 0 段数量
                int missingSegments = 8 - (leftSide.Length + rightSide.Length);

                if (missingSegments < 0)
                {
                    throw new ArgumentException("Invalid IPv6 address, too many segments.");
                }

                // 扩展地址，填充 0 段
                var expandedAddress = leftSide.Concat(Enumerable.Repeat("0", missingSegments)).Concat(rightSide).ToArray();

                // 将扩展后的地址合并为一个完整字符串
                return string.Join(":", expandedAddress);
            }
            else
            {
                // 正常的完整 IPv6 地址
                return address;
            }
        }
    }
}

